from typing import TYPE_CHECKING, List
import pygame
from pygame import draw
from const import (
    LIGHT_GRAY, SCREEN_WIDTH, SCREEN_HEIGHT,
    PLAYER_PANEL_WIDTH, 
    STATUS_PANEL_HEIGHT, STATUS_INFO_WIDTH,
    GRAY, BLACK, WHITE,
    SKILL_BUTTON_CLICKED_EVENT,
    Skill
)

if TYPE_CHECKING:
    from model import Model, PlayerManager
    from .renderer import FontManager


class SkillButton:
    """技能按钮类"""
    def __init__(self, x, y, width, height, name: Skill):
        self.rect = pygame.Rect(x, y, width, height)
        self.name = name
        self.is_selected = False
        self.is_hovered = False
        self.color = LIGHT_GRAY

    # 修改 draw 方法签名，增加 remaining_uses 参数
    def draw(self, surface: pygame.Surface, font: pygame.font.Font, remaining_uses: int):
        color = WHITE if self.is_selected or self.is_hovered else self.color
        radius = 5
        rect = self.rect
        pygame.draw.rect(surface, color, rect, border_radius=radius)
        pygame.draw.rect(surface, BLACK, rect, width=2, border_radius=radius)

        text_color = BLACK
        # 修改文本内容，包含剩余次数
        display_text = f"{self.name.value}: {remaining_uses}"
        text = font.render(display_text, True, text_color)
        text_rect = text.get_rect(center=self.rect.center)
        surface.blit(text, text_rect)

    def check_hover(self, mouse_pos):
        """检查鼠标是否悬停在按钮上"""
        
        if self.rect.collidepoint(mouse_pos):
            self.is_hovered = True
        else:
            self.is_hovered = False

    def select(self):
        """选中按钮"""
        self.is_selected = True

    def deselect(self):
        """取消选中按钮"""
        self.is_selected = False


class StatusBarRenderer:

    font_mgr: 'FontManager'

    def __init__(self, screen, font_mgr: 'FontManager'):
        self.screen = screen
        self.font_mgr = font_mgr
        
        # 设置常量值
        self.small_font = self.font_mgr.get_font(12)
        self.message_font = self.font_mgr.get_font(20)
        self.button_margin_top = 5
        self.button_row_spacing = 10
        self.button_margin_side = 10
        self.button_height_ratio = 0.4  # 按钮高度占总高度的比例
        self.right_margin = 20  # 按钮组距离右边界的距离
        
        # 存储技能按钮
        self.skill_buttons: List[SkillButton] = []
        self.selected_button: SkillButton = None
        
        # 记录上次绘制的玩家和技能，用于优化按钮重绘
        self._last_drawn_player = None
        self._last_drawn_skills_tuple = None
        
        

    def handle_mouse_hover(self, mouse_pos: tuple[int, int]):
        """
        处理鼠标悬停事件
        """

        # 优化边界检查，确保只在状态栏区域内检查悬停
        status_bar_rect = pygame.Rect(PLAYER_PANEL_WIDTH, 0, SCREEN_WIDTH - PLAYER_PANEL_WIDTH, STATUS_PANEL_HEIGHT)
        if status_bar_rect.collidepoint(mouse_pos):

            for button in self.skill_buttons:
                button.check_hover(mouse_pos)


    def handle_click(self, mouse_pos: tuple[int, int], model: 'Model') -> bool:
        """
        处理技能栏区域的点击事件

        Args:
            mouse_pos: 鼠标点击位置坐标

        Returns:
            bool: 如果点击在玩家区域内返回True，否则返回False
        """
        # 判断点击是否在技能栏区域内
        mx, my = mouse_pos
        if mx >= PLAYER_PANEL_WIDTH and my <= STATUS_PANEL_HEIGHT:
            # 检查是否点击了技能图标
            for button in self.skill_buttons:
                if button.rect.collidepoint(mouse_pos):
                    # 处理按钮点击
                    pygame.event.post(pygame.event.Event(SKILL_BUTTON_CLICKED_EVENT, skill=button.name))
                    return True
            return True
        return False
    
    def unselect_all_buttons(self):
        """
        取消所有按钮的选中状态
        """
        for button in self.skill_buttons:
            button.deselect()
    

    def draw_status_bar(self, model: 'Model'):
        """
        绘制状态栏
        """
        # --- 修改代码开始 ---
        # 绘制背景和分割线 (移到开头)
        draw.rect(self.screen, GRAY, 
                       (PLAYER_PANEL_WIDTH, 0, 
                        SCREEN_WIDTH - PLAYER_PANEL_WIDTH, STATUS_PANEL_HEIGHT)) # 修正宽度计算
        # 绘制上下分割线
        draw.line(self.screen, BLACK, (PLAYER_PANEL_WIDTH, STATUS_PANEL_HEIGHT), (SCREEN_WIDTH, STATUS_PANEL_HEIGHT), 2)
        # 绘制左右分割线
        draw.line(self.screen, BLACK, (PLAYER_PANEL_WIDTH, 0), (PLAYER_PANEL_WIDTH, STATUS_PANEL_HEIGHT), 2)
        # 绘制信息区和技能区的分割线 (可选)
        # info_skill_divider_x = PLAYER_PANEL_WIDTH + STATUS_INFO_WIDTH
        # draw.line(self.screen, BLACK, (info_skill_divider_x, 0), (info_skill_divider_x, STATUS_PANEL_HEIGHT), 2)

        
        # 右侧技能图标区域
        current_player = model.player_manager.current_player
        available_skills = current_player.available_skills
        current_skills_tuple = tuple(available_skills) # 转换为元组以便比较
        skill_uses = current_player.skill_uses # 获取技能使用次数

        # 检查玩家或技能列表是否发生变化 (优化逻辑保持不变)
        if current_player == self._last_drawn_player and current_skills_tuple == self._last_drawn_skills_tuple:

            # 检查玩家的技能是否选中
            skill = model.selected_skill

            if skill is None and self.selected_button is not None:
                self.unselect_all_buttons() # 如果没有选中技能，则取消所有按钮的选中状态
                self.selected_button = None # 清空选中按钮的记录
            elif skill is not None:
                # 选中技能，将其按钮设为白色
                for button in self.skill_buttons:
                    if button.name == skill and skill in available_skills:
                        button.select()
                        self.selected_button = button # 记录选中的按钮
                    else:
                        button.deselect()
            

            # 状态未变，仅重绘现有按钮，但传递最新的剩余次数
            for button in self.skill_buttons:
                # 从 skill_uses 获取当前按钮技能的剩余次数
                uses = skill_uses.get(button.name, 0) # 如果找不到，默认为0
                button.draw(self.screen, self.small_font, uses) # 传递剩余次数
        else:
            # 状态改变，重新创建按钮
            self.skill_buttons = [] # 清空旧按钮
            self._last_drawn_player = current_player
            self._last_drawn_skills_tuple = current_skills_tuple

            if not available_skills: # 如果没有技能，则不执行后续操作
                 return # 直接返回，因为没有按钮需要创建和绘制

            # 考虑右边距，计算技能区域实际宽度
            skill_area_width = SCREEN_WIDTH - (PLAYER_PANEL_WIDTH + STATUS_INFO_WIDTH) - self.right_margin
            
            # 计算每个技能按钮的宽度和高度
            buttons_per_row = (len(available_skills) + 1) // 2
            buttons_per_row = max(1, buttons_per_row) # 防止除零错误

            
            # 简化布局：固定按钮宽度，或者基于可用空间计算
            icon_height = (STATUS_PANEL_HEIGHT - self.button_margin_top*2 - self.button_row_spacing) * self.button_height_ratio
            # 设定一个最大宽度，例如高度的3倍
            max_icon_width = icon_height * 3
            # 计算基于可用空间的宽度
            space_based_width = (skill_area_width - (buttons_per_row + 1) * self.button_margin_side) // buttons_per_row if buttons_per_row > 0 else max_icon_width
            icon_width = max(10, min(space_based_width, max_icon_width)) # 确保宽度至少为10，且不超过最大值和可用空间计算值

            # 计算两行按钮的总高度
            total_buttons_height = 2 * icon_height + self.button_row_spacing
            
            # 计算垂直居中的起始y坐标
            start_y = (STATUS_PANEL_HEIGHT - total_buttons_height) / 2
            

            for i, skill in enumerate(available_skills):
                # 计算行和列
                row = i // buttons_per_row  # 0 为第一行，1 为第二行
                col = i % buttons_per_row   # 从左到右的列索引 (调整为从左到右布局可能更直观)
                
                # 从右侧开始计算 x 坐标 (保持原逻辑)
                # (col + 1) 表示从右数的第几个按钮位置
                x = SCREEN_WIDTH - self.right_margin - (col + 1) * icon_width - (col + 1) * self.button_margin_side
                
                # 使用垂直居中的y坐标
                y = start_y + row * (icon_height + self.button_row_spacing)
                
                # 创建技能图标
                skill_button = SkillButton(
                    x=x,
                    y=y,
                    width=icon_width,
                    height=icon_height,
                    name=skill
                )
                # 将按钮添加到列表中
                self.skill_buttons.append(skill_button)
                
                # 绘制新创建的按钮，传递剩余次数
                uses = skill_uses.get(skill, 0) # 获取新按钮技能的剩余次数
                skill_button.draw(self.screen, self.small_font, uses) # 传递剩余次数
        # --- 修改代码结束 ---
            
    def render_event_message(self, message: str):
        """
        在状态栏左侧区域渲染事件消息，支持自动换行
        
        Args:
            message: 要显示的消息文本
        """
        if not message:
            return
            
        # 消息区域
        message_area = pygame.Rect(
            PLAYER_PANEL_WIDTH + 20,  # 左边距10像素
            10,  # 上边距5像素
            STATUS_INFO_WIDTH - 20,  # 宽度减去左右边距
            STATUS_PANEL_HEIGHT - 10  # 高度减去上下边距
        )
        
        # 文本自动换行
        words = message.split(' ')
        lines = []
        current_line = []
        current_width = 0
        
        for word in words:
            word_surface = self.message_font.render(word + ' ', True, BLACK)
            word_width = word_surface.get_width()
            
            if current_width + word_width <= message_area.width:
                current_line.append(word)
                current_width += word_width
            else:
                lines.append(' '.join(current_line))
                current_line = [word]
                current_width = word_width
                
        if current_line:
            lines.append(' '.join(current_line))
        
        # 绘制文本
        y_offset = message_area.y
        for line in lines:
            if y_offset + self.message_font.get_height() > message_area.bottom:
                break  # 超出显示区域，不再显示
                
            text_surface = self.message_font.render(line, True, BLACK)
            self.screen.blit(text_surface, (message_area.x, y_offset))
            y_offset += self.message_font.get_height()